package com.qingsong.component;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONUtil;
import com.qingsong.exception.ServiceException;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

/**
 * @author qingsong
 */
@Aspect
@Component
public class ServiceAspect {

    private static final Logger log = LoggerFactory.getLogger(ServiceAspect.class);

    @Around("execution(public * com.qingsong.service.impl..*(..))")
    @SneakyThrows
    public Object aroundAdvice(ProceedingJoinPoint pjp) {
        // 前置: 获取方法参数
        Object[] args = pjp.getArgs();

        // 前置: 组装完整业务方法名: 类名.方法名()
        String className = pjp.getTarget().toString();
        className = className.substring(className.lastIndexOf('.') + 1, className.indexOf('@'));
        String methodName = pjp.getSignature().getName();
        methodName = className + "." + methodName + "()";

        // 前置: 检查参数中是否存在空值
        if (ObjectUtil.hasNull(args)) {
            throw new ServiceException("业务方法 " + methodName + " 中存在null值参数");
        }

        // 调用
        Object result = pjp.proceed(args);

        // 后置: 记录调用日志
        log.info(String.format("\n" +
                "================ 业务日志 ================\n" +
                "业务方法: %s\n" +
                "业务参数: %s\n" +
                "响应数据: %s\n" +
                "=====================================",
                methodName,
                JSONUtil.toJsonStr(args),
                JSONUtil.toJsonStr(result)));

        return result;
    }
}